a tool for shared writing and social publishing
at feature/mention-services 87 lines 2.5 kB view raw
1import { z } from "zod"; 2import { makeRoute } from "../lib"; 3import type { Env } from "./route"; 4import { idResolver } from "app/(home-pages)/reader/idResolver"; 5import { supabaseServerClient } from "supabase/serverClient"; 6import { Agent } from "@atproto/api"; 7import { getIdentityData } from "actions/getIdentityData"; 8import { createOauthClient } from "src/atproto-oauth"; 9import { 10 normalizePublicationRow, 11 hasValidPublication, 12} from "src/utils/normalizeRecords"; 13import { deduplicateByUri } from "src/utils/deduplicateRecords"; 14 15export type GetProfileDataReturnType = Awaited< 16 ReturnType<(typeof get_profile_data)["handler"]> 17>; 18 19export const get_profile_data = makeRoute({ 20 route: "get_profile_data", 21 input: z.object({ 22 didOrHandle: z.string(), 23 }), 24 handler: async ({ didOrHandle }, { supabase }: Pick<Env, "supabase">) => { 25 // Resolve handle to DID if necessary 26 let did = didOrHandle; 27 28 if (!didOrHandle.startsWith("did:")) { 29 const resolved = await idResolver.handle.resolve(didOrHandle); 30 if (!resolved) { 31 throw new Error("Could not resolve handle to DID"); 32 } 33 did = resolved; 34 } 35 let agent; 36 let authed_identity = await getIdentityData(); 37 if (authed_identity?.atp_did) { 38 try { 39 const oauthClient = await createOauthClient(); 40 let credentialSession = await oauthClient.restore( 41 authed_identity.atp_did, 42 ); 43 agent = new Agent(credentialSession); 44 } catch (e) { 45 agent = new Agent({ 46 service: "https://public.api.bsky.app", 47 }); 48 } 49 } else { 50 agent = new Agent({ 51 service: "https://public.api.bsky.app", 52 }); 53 } 54 55 let profileReq = agent.app.bsky.actor 56 .getProfile({ actor: did }) 57 .then( 58 (res) => res.data, 59 () => undefined, 60 ); 61 62 let publicationsReq = supabase 63 .from("publications") 64 .select("*") 65 .eq("identity_did", did); 66 67 let [profile, { data: rawPublications }] = await Promise.all([ 68 profileReq, 69 publicationsReq, 70 ]); 71 72 // Deduplicate records that may exist under both pub.leaflet and site.standard namespaces 73 const publications = deduplicateByUri(rawPublications || []); 74 75 // Normalize publication records before returning 76 const normalizedPublications = publications 77 .map(normalizePublicationRow) 78 .filter(hasValidPublication); 79 80 return { 81 result: { 82 profile, 83 publications: normalizedPublications, 84 }, 85 }; 86 }, 87});